<template>
  <div class="contBody">
    <h2 class="title">HeatMap</h2>
    <div id="HeatMap" class="map__x"></div>
  </div>
</template>

<script>
import { Map, View } from "ol"; // 地图实例方法、视图方法
import { Heatmap as HeatmapLayer, Tile as TileLayer } from "ol/layer";
import GeoJSON from "ol/format/GeoJSON";
import VectorSource from "ol/source/Vector";
import XYZ from "ol/source/XYZ";
import "ol/ol.css"; // 地图样式

import earthquake from "@/assets/json/earthquake.json";
import china from "@/assets/json/china.json";

export default {
  name: "HeatMap",
  data() {
    return {
      map: null,
    };
  },
  mounted() {
    this.initMap();
  },
  methods: {
    async initMap() {
      const heatVector = new HeatmapLayer({
        source: new VectorSource({
          features: new GeoJSON().readFeatures(earthquake),
        }),
        zIndex: 10,
        gradient: ["#00f", "#0ff", "#f00"], // 渐变色
        radius: 15,
        blur: 20,
        weight: function (feature) {
          const magnitude = feature.get("mag");
          return magnitude - 3;
        },
      });

      await this.__OnLoadProvinceAreaRange();

      // 地图实例
      this.map = new Map({
        target: "HeatMap", // 对应页面里 id 为 map 的元素
        layers: [
          // 图层
          new TileLayer({
            title: "高德地图",
            source: new XYZ({
              url: "http://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}",
              wrapX: true,
            }),
            preload: Infinity,
            zIndex: 1,
            visible: true,
          }),
          heatVector,
        ],
        view: new View({
          center: [120, 30],
          projection: "EPSG:4326",
          minZoom: 2,
          zoom: 4,
        }),
      });

      // 判断鼠标点击位置是否在范围内
      this.map.on("click", async (evt) => {
        //鼠标单击点坐标
        let point = evt.coordinate;
        const status = await this.IsPtInPoly(
          point[0],
          point[1],
          this.LonAndLatInfoByP[0].coordinates
        );
        console.log("当前层级:", this.map.getView().getZoom());
        console.log(
          "鼠标所在位置:",
          point,
          this.LonAndLatInfoByP[0].coordinates,
          status
        );
      });
    },

    /**
     * 加载五省行政区域范围
     */
    async __OnLoadProvinceAreaRange() {
      this.LonAndLatInfoByP = [];
      china.features.forEach((info) => {
        let array = [];
        let coordinates = info.geometry.coordinates;
        if (coordinates.length == 1) {
          let coordinatesArray = coordinates[0][0];
          for (let i = 0; i < coordinatesArray.length; i++) {
            let convertPoint = coordinatesArray[i];
            array.push({ lng: convertPoint[0], lat: convertPoint[1] });
          }
        } else if (coordinates.length > 1) {
          coordinates.forEach((item) => {
            let coordinatesArray = item[0];
            for (let i = 0; i < coordinatesArray.length; i++) {
              let convertPoint = coordinatesArray[i];
              array.push({ lng: convertPoint[0], lat: convertPoint[1] });
            }
          });
        }
        this.LonAndLatInfoByP.push({
          adcode: info.properties.adcode,
          name: info.properties.name,
          coordinates: array,
        });
      });
    },

    /**
     * 某个点是否在某个区域内(来处:https://blog.csdn.net/neil89/article/details/50240481)
     * @param {*} ALon
     * @param {*} ALat
     * @param {*} APoints 范围数组经纬度
     * @returns
     */
    IsPtInPoly(ALon, ALat, APoints) {
      let iSum = 0,
        iCount;
      let dLon1, dLon2, dLat1, dLat2, dLon;
      if (APoints.length < 3) return false;
      iCount = APoints.length;
      for (let i = 0; i < iCount; i++) {
        if (i == iCount - 1) {
          dLon1 = APoints[i].lng;
          dLat1 = APoints[i].lat;
          dLon2 = APoints[0].lng;
          dLat2 = APoints[0].lat;
        } else {
          dLon1 = APoints[i].lng;
          dLat1 = APoints[i].lat;
          dLon2 = APoints[i + 1].lng;
          dLat2 = APoints[i + 1].lat;
        }
        //以下语句判断A点是否在边的两端点的水平平行线之间，在则可能有交点，开始判断交点是否在左射线上
        if (
          (ALat >= dLat1 && ALat < dLat2) ||
          (ALat >= dLat2 && ALat < dLat1)
        ) {
          if (Math.abs(dLat1 - dLat2) > 0) {
            //得到 A点向左射线与边的交点的x坐标：
            dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);
            if (dLon < ALon) iSum++;
          }
        }
      }
      if (iSum % 2 != 0) return true;
      return false;
    },
  },
};
</script>

<style lang="css" scoped>
.contBody .title {
  padding: 0 0 24px;
}
.map__x {
  width: 100%;
  height: 600px;
  border: 1px solid #eee;
  background: rgba(0, 0, 0, 1);
}

.btn {
  text-align: left;
}
</style>
